From 2e9e5c7ead4240bcb41f82b438959d529727e623 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 28 Feb 2006 10:13:26 +0100 Subject: [PATCH] Fix SVM guest pin timer migration logic. Signed-off-by: Tom Woller --- xen/arch/x86/hvm/svm/svm.c | 54 ++++++++++++++++++++---------- xen/arch/x86/hvm/svm/vmcb.c | 13 ++++--- xen/include/asm-x86/hvm/svm/svm.h | 2 ++ xen/include/asm-x86/hvm/svm/vmcb.h | 3 +- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 45dcaf28a1..568568d8e4 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -820,8 +820,29 @@ void svm_relinquish_resources(struct vcpu *v) void arch_svm_do_resume(struct vcpu *v) { - svm_do_resume(v); - reset_stack_and_jump(svm_asm_do_resume); + /* pinning VCPU to a different core? */ + if ( v->arch.hvm_svm.launch_core == smp_processor_id()) { + svm_do_resume( v ); + reset_stack_and_jump( svm_asm_do_resume ); + } + else { + printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() ); + v->arch.hvm_svm.launch_core = smp_processor_id(); + svm_migrate_timers( v ); + svm_do_resume( v ); + reset_stack_and_jump( svm_asm_do_resume ); + } +} + + +void svm_migrate_timers(struct vcpu *v) +{ + struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit); + + migrate_timer( &vpit->pit_timer, v->processor ); + migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor ); + if ( hvm_apic_support(v->domain) && VLAPIC( v )) + migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor ); } @@ -2668,26 +2689,23 @@ asmlinkage void svm_asid(void) { struct vcpu *v = current; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - int core = smp_processor_id(); - int oldcore = v->arch.hvm_svm.core; - /* - * if need to assign new asid or if switching cores, - * then retire asid for old core, and assign new for new core. - */ - if( v->arch.hvm_svm.core != core ) { - if (svm_dbg_on) - printk("old core %d new core %d\n",(int)v->arch.hvm_svm.core,(int)core); - v->arch.hvm_svm.core = core; - } - if( test_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags) || - (oldcore != core)) { - if(!asidpool_assign_next(vmcb, 1, - oldcore, core)) { + + /* + * if need to assign new asid, or if switching cores, + * retire asid for the old core, and assign a new asid to the current core. + */ + if ( test_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags ) || + ( v->arch.hvm_svm.asid_core != v->arch.hvm_svm.launch_core )) { + /* recycle asid */ + if ( !asidpool_assign_next( vmcb, 1, + v->arch.hvm_svm.asid_core, v->arch.hvm_svm.launch_core )) { /* If we get here, we have a major problem */ domain_crash_synchronous(); } + + v->arch.hvm_svm.asid_core = v->arch.hvm_svm.launch_core; + clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags ); } - clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags); } /* diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 0fa4040e90..f67fb9aafb 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -306,7 +306,7 @@ void destroy_vmcb(struct arch_svm_struct *arch_svm) { if(arch_svm->vmcb != NULL) { - asidpool_retire(arch_svm->vmcb, arch_svm->core); + asidpool_retire(arch_svm->vmcb, arch_svm->asid_core); free_vmcb(arch_svm->vmcb); } if(arch_svm->iopm != NULL) { @@ -404,18 +404,17 @@ err_out: void svm_do_launch(struct vcpu *v) { - /* Update CR3, GDT, LDT, TR */ - struct vmcb_struct *vmcb; + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; int core = smp_processor_id(); - vmcb = v->arch.hvm_svm.vmcb; ASSERT(vmcb); + /* Update CR3, GDT, LDT, TR */ svm_stts(v); - /* current core is the one we will perform the vmrun on */ - v->arch.hvm_svm.core = core; + /* current core is the one we intend to perform the VMRUN on */ + v->arch.hvm_svm.launch_core = v->arch.hvm_svm.asid_core = core; clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags); - if ( !asidpool_assign_next(vmcb, 0, core, core) ) + if ( !asidpool_assign_next( vmcb, 0, core, core )) BUG(); if (v->vcpu_id == 0) diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h index 097fd2da1a..c6c848ec90 100644 --- a/xen/include/asm-x86/hvm/svm/svm.h +++ b/xen/include/asm-x86/hvm/svm/svm.h @@ -54,6 +54,8 @@ extern int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa); /* For debugging. Remove when no longer needed. */ extern void svm_dump_host_regs(const char *from); +extern void svm_migrate_timers(struct vcpu *v); + /* ASID API */ enum { ASID_AVAILABLE = 0, diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h index 97a8837c21..b9abe0cd1a 100644 --- a/xen/include/asm-x86/hvm/svm/vmcb.h +++ b/xen/include/asm-x86/hvm/svm/vmcb.h @@ -457,7 +457,8 @@ struct arch_svm_struct { u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */ int injecting_event; int saved_irq_vector; - u32 core; /* cpu of last vmexit */ + u32 launch_core; + u32 asid_core; unsigned long flags; /* VMCB flags */ unsigned long cpu_shadow_cr0; /* copy of guest read shadow CR0 */ -- 2.30.2